home *** CD-ROM | disk | FTP | other *** search
- #define NCARGS 2000
- /*
- * Copyright (c) 1980 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
- /* 24-DEC-92 Modified for use with VMS-fsp V2.6.3 <S.A.Pechler@bdk.tue.nl>
- * 27-JAN-93 Stripped leading spaces in arguments <S.A.Pechler@bdk.tue.nl>
- * 17-MAY-93 Removed all VMS modifications <S.A.Pechler@bdk.tue.nl>
- */
-
- #ifndef lint
- static char sccsid[] = "@(#)glob.c 5.4 (Berkeley) 6/29/88";
- #endif /* not lint */
-
- /*
- * C-shell glob for random programs.
- */
-
- #include "tweak.h"
- #include "client_def.h"
- #include "c_extern.h"
-
- #define QUOTE 0200
- #define TRIM 0177
- #define eq(a,b) (strcmp(a, b)==0)
- #define GAVSIZ (NCARGS/6)
- #define isdir(d) ((d.st_mode & S_IFMT) == S_IFDIR)
-
- static char **gargv; /* Pointer to the (stack) arglist */
- static int gargc; /* Number args in gargv */
- static int gnleft;
- static int gflag;
- char *globerr;
- extern int errno;
-
- static int globcnt;
-
- char *globchars = "`{[*?";
-
- static char *gpath, *gpathp, *lastgpathp;
- static int globbed;
- static char *entp;
- static char **sortbas;
-
- static int any PROTO2(register int, c, register char *, s)
- {
- while (*s)
- if (*s++ == c) return(1);
- return(0);
- }
-
- static int tglob PROTO1(char, c)
- {
- if (any(c, globchars))
- gflag |= c == '{' ? 2 : 1;
- return (c);
- }
-
- static int addpath PROTO1(char, c)
- {
- if (gpathp >= lastgpathp) globerr = "Pathname too long";
- else {
- *gpathp++ = c;
- *gpathp = 0;
- }
- }
-
- static int ginit PROTO1(char **, agargv)
- {
- agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
- gnleft = NCARGS - 4;
- }
-
- static int sort PROTO0((void))
- {
- register char **p1, **p2, *c;
- char **Gvp = &gargv[gargc];
-
- p1 = sortbas;
- while (p1 < Gvp-1) {
- p2 = p1;
- while (++p2 < Gvp)
- if (strcmp(*p1, *p2) > 0) {
- c = *p1;
- *p1 = *p2;
- *p2 = c;
- }
- p1++;
- }
- sortbas = Gvp;
- }
-
- static char *strspl PROTO2(register char *, cp, register char *, dp)
- {
- register char *ep = (char *)malloc((unsigned)(strlen(cp) + strlen(dp) + 1));
-
- if (ep == (char *)0) {
- perror("Out of memory 1");
- exit(1);
- }
- (void) strcpy(ep, cp);
- (void) strcat(ep, dp);
- return (ep);
- }
-
- static int Gcat PROTO2(char *, s1, char *, s2)
- {
- register int len = strlen(s1) + strlen(s2) + 1;
-
- if (len >= gnleft || gargc >= GAVSIZ - 1) globerr = "Arguments too long";
- else {
- gargc++;
- gnleft -= len;
- gargv[gargc] = 0;
- gargv[gargc - 1] = strspl(s1, s2);
- }
- }
-
- static int execbrc PROTO0((char *, char *));
-
- static int expand PROTO1(char *, as)
- {
- register char *cs;
- register char *sgpathp, *oldcs;
- struct stat stb;
-
- sgpathp = gpathp;
- cs = as;
- while (!any(*cs, globchars)) {
- if (*cs == 0) {
- if (!globbed) Gcat(gpath, "");
- else if (util_stat(gpath, &stb) >= 0) {
- Gcat(gpath, "");
- globcnt++;
- }
- break;
- }
- addpath(*cs++);
- }
- if(*cs) {
- oldcs = cs;
- while (cs > as && *cs != '/') {
- cs--; gpathp--;
- }
- if (*cs == '/') {
- cs++; gpathp++;
- }
- *gpathp = 0;
- if (*oldcs == '{') {
- (void) execbrc(cs, ((char *)0));
- return;
- }
- matchdir(cs);
- }
- gpathp = sgpathp;
- *gpathp = 0;
- }
-
- static int amatch PROTO2(char *, s, char *, p)
- {
- register int scc;
- int ok, lc;
- char *sgpathp;
- struct stat stb;
- int c, cc;
-
- globbed = 1;
- for (;;) {
- scc = *s++ & TRIM;
- switch (c = *p++) {
- case '{':
- return (execbrc(p - 1, s - 1));
- case '[':
- ok = 0;
- lc = 077777;
- while (cc = *p++) {
- if (cc == ']') {
- if (ok) break;
- return (0);
- }
- if (cc == '-') {
- if (lc <= scc && scc <= *p++) ok++;
- } else if (scc == (lc = cc)) ok++;
- }
- if (cc == 0) {
- if (ok) p--;
- else return 0;
- }
- continue;
- case '*':
- if (!*p) return (1);
- if (*p == '/') {
- p++;
- goto slash;
- }
- s--;
- do {
- if (amatch(s, p)) return (1);
- } while (*s++);
- return (0);
- case 0:
- return (scc == 0);
- default:
- if (c != scc) return (0);
- continue;
- case '?':
- if (scc == 0) return (0);
- continue;
- case '/':
- if (scc) return (0);
- slash:
- s = entp;
- sgpathp = gpathp;
- while (*s) addpath(*s++);
- addpath('/');
- if (util_stat(gpath, &stb) == 0 && isdir(stb))
- if (*p == 0) {
- Gcat(gpath, "");
- globcnt++;
- } else expand(p);
- gpathp = sgpathp;
- *gpathp = 0;
- return (0);
- }
- }
- }
-
- static int match PROTO2(char *, s, char *, p)
- {
- register int c;
- register char *sentp;
- char sglobbed = globbed;
-
- if (*s == '.' && *p != '.') return (0);
- sentp = entp;
- entp = s;
- c = amatch(s, p);
- entp = sentp;
- globbed = sglobbed;
- return (c);
- }
-
- int matchdir PROTO1(char *, pattern)
- {
- struct stat stb;
- register struct rdirent *dp;
- RDIR *dirp;
-
- dirp = util_opendir(gpath);
- if (dirp == NULL) {
- if (globbed) return;
- globerr = "Bad directory components";
- return;
- }
- if (util_stat(gpath, &stb) < 0) {
- util_closedir(dirp);
- globerr = "Bad directory components";
- }
- if (!isdir(stb)) {
- errno = ENOTDIR;
- util_closedir(dirp);
- globerr = "Bad directory components";
- }
- while ((dp = util_readdir(dirp)) != NULL) {
- if (dp->d_fileno == 0) continue;
- if (match(dp->d_name, pattern)) {
- Gcat(gpath, dp->d_name);
- globcnt++;
- }
- }
- util_closedir(dirp);
- }
-
- static int execbrc PROTO2(char *, p, char *, s)
- {
- char restbuf[BUFSIZ + 2];
- register char *pe, *pm, *pl;
- int brclev = 0;
- char *lm, savec, *sgpathp;
-
- for (lm = restbuf; *p != '{'; *lm++ = *p++);
- for (pe = ++p; *pe; pe++)
- switch (*pe) {
- case '{':
- brclev++;
- continue;
- case '}':
- if (brclev == 0) goto pend;
- brclev--;
- continue;
- case '[':
- for (pe++; *pe && *pe != ']'; pe++);
- }
- pend:
- brclev = 0;
- for (pl = pm = p; pm <= pe; pm++)
- switch (*pm & (QUOTE|TRIM)) {
- case '{':
- brclev++;
- continue;
- case '}':
- if (brclev) {
- brclev--;
- continue;
- }
- goto doit;
- case ','|QUOTE:
- case ',':
- if (brclev) continue;
- doit:
- savec = *pm;
- *pm = 0;
- (void) strcpy(lm, pl);
- (void) strcat(restbuf, pe + 1);
- *pm = savec;
- if (s == 0) {
- sgpathp = gpathp;
- expand(restbuf);
- gpathp = sgpathp;
- *gpathp = 0;
- } else if (amatch(s, restbuf)) return (1);
- sort();
- pl = pm + 1;
- if (brclev) return (0);
- continue;
- case '[':
- for (pm++; *pm && *pm != ']'; pm++);
- if (!*pm) pm--;
- continue;
- }
- if (brclev) goto doit;
- return (0);
- }
-
- int acollect PROTO1(register char *, as)
- {
- register int ogargc = gargc;
-
- gpathp = gpath; *gpathp = 0; globbed = 0;
- expand(as);
- if (gargc != ogargc) sort();
- }
-
- static int collect PROTO1(register char *, as)
- {
- if (eq(as, "{") || eq(as, "{}")) {
- Gcat(as, "");
- sort();
- } else acollect(as);
- }
-
- static int blkfree PROTO1(char **, av0)
- {
- register char **av = av0;
-
- while (*av) free(*av++);
- }
-
- static int blklen PROTO1(register char **, av)
- {
- register int i = 0;
-
- while (*av++) i++;
- return (i);
- }
-
- static char **blkcpy PROTO2(char **, oav, register char **, bv)
- {
- register char **av = oav;
-
- while (*av++ = *bv++) continue;
- return (oav);
- }
-
- static char **copyblk PROTO1(register char **, v)
- {
- register char **nv;
-
- nv = (char **)malloc((unsigned)((blklen(v) + 1) * sizeof(char **)));
- if (nv == (char **)0) {
- perror("Out of memory 2");
- exit(2);
- }
- return (blkcpy(nv, v));
- }
-
- #ifdef HAVE_ANSI_PROTO
- typedef int (*charfunc) (char) ;
- static int rscan (register char **t, charfunc f)
- #else
- static int rscan(t, f)
- register char **t;
- int (*f)();
- #endif
- {
- register char *p, c;
-
- while (p = *t++) {
- #ifdef HAVE_ANSI_PROTO
- if (f == (charfunc) tglob)
- #else
- if (f == tglob)
- #endif
- if (*p == '~') gflag |= 2;
- else if (eq(p, "{") || eq(p, "{}")) continue;
- while (c = *p++) (*f)(c);
- }
- }
-
- char **glob PROTO1(register char *, v)
- {
- char agpath[BUFSIZ];
- char *agargv[GAVSIZ];
- char *vv[2];
- vv[0] = v;
- vv[1] = 0;
- gflag = 0;
- #ifdef HAVE_ANSI_PROTO
- rscan(vv, (charfunc) tglob);
- #else
- rscan(vv, tglob);
- #endif
- if (gflag == 0) return (copyblk(vv));
-
- globerr = 0;
- gpath = agpath; gpathp = gpath; *gpathp = 0;
- lastgpathp = &gpath[sizeof agpath - 2];
- ginit(agargv); globcnt = 0;
- collect(v);
- if (globcnt == 0 && (gflag&1)) {
- blkfree(gargv), gargv = 0;
- return (0);
- } else return (gargv = copyblk(gargv));
- }
-